<template>
  <div class="gantt">
    <div class="legend">
      <!-- 渲染图例 -->
      <i class="plan"></i>
      <label>计划</label>
      <i class="real"></i>
      <label>实际</label>
    </div>
    <el-table :data="data" v-bind="props">
      <!-- 渲染表格 -->
      <el-table-column v-for="(column, index) in columnsConfig" :key="index" v-bind="column"/>
      <el-table-column v-for="monthItem in monthData" :key="monthItem.month" align="center" min-width="80"
        :prop="monthItem.month" :label="monthItem.month">
        <template #header>
          <span>{{ monthItem.month.substring(5) + '月' }}</span>
        </template>
        <el-table-column v-for="day in monthItem.dayArray" :key="day" align="center" :width="50" :prop="day">
          <template #header>
            <span>{{ day.substring(8) }}</span>
          </template>
          <template #default="scope">
            <i class="plan" v-if="showPlan(scope)"></i>
            <i class="empty" v-else></i>
            <i class="real" v-if="showReal(scope)"></i>
            <i class="empty" v-else></i>
          </template>
        </el-table-column>
      </el-table-column>
    </el-table>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const props = defineProps({
  treeConfig:{
    type: Object,
    default:()=>{
      return null
    }
  },
  data: {
    type: Array,
    default: ()=>[]
  },
  columnsConfig: {// 定义前面字段信息
    type: Array,
    default: ()=>[]
  },
  ganttConfig: {
    type: Object,
    default: ()=>{
      return {
        dateType:'ym',// ym-年月、md-月日,dh-日时,hm-时分,会根据数据跨度自动调整
        planStart: 'planStart',
        planEnd: 'planEnd',
        realStart: 'realStart',
        realEnd: 'realEnd'
      }
    }
  }
})

const monthData = ref({})

const init = () => {
  let minDate = undefined
  let maxDate = undefined

  props.data.forEach((row, index) => {
    let current = new Date(row[props.ganttConfig.planStart])
    if (minDate) {
      minDate = minDate.getTime() < current.getTime() ? minDate : current
    } else {
      minDate = current
    }
    current = new Date(row[props.ganttConfig.planEnd])
    if (maxDate) {
      maxDate = maxDate.getTime() > current.getTime() ? maxDate : current
    } else {
      maxDate = current
    }
    current =
      props.ganttConfig.realStart || row[props.ganttConfig.realStart]
        ? new Date(row[props.ganttConfig.realStart])
        : undefined
    if (current) {
      minDate = minDate.getTime() < current.getTime() ? minDate : current
    }
    current =
      props.ganttConfig.realEnd || row[props.ganttConfig.realEnd]
        ? new Date(row[props.ganttConfig.realEnd])
        : undefined
    if (current) {
      maxDate = maxDate.getTime() > current.getTime() ? maxDate : current
    }
  })

  // 甘特图前后各放宽2天
  minDate = new Date(minDate.getTime() - 2 * 24 * 60 * 60 * 1000)
  maxDate = new Date(maxDate.getTime() + 2 * 24 * 60 * 60 * 1000)
  let current = new Date(format(minDate))
  while (!isAfter(current, maxDate)) {
    const month = formatYearMonth(current)
    const day = format(current)
    if (monthData.value[month]) {
      monthData.value[month].dayArray.push(day)
    } else {
      monthData.value[month] = {
        month: month,
        dayArray: [day]
      }
    }
    // 加一天
    current = after(current)
  }
}
/**
 * 格式化 YYYY-MM-DD
 */
const format = (date) => {
  const day = String(date.getDate()).padStart(2, '0')
  return formatYearMonth(date) + '-' + day
}
/**
 * 格式化 YYYY-MM
 */
const formatYearMonth = (date) => {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  return year + '-' + month
}
/**
 * 加一天
 */
const after = (date) => {
  return new Date(date.getTime() + 24 * 60 * 60 * 1000)
}
/**
 * date1是否大于等于date2
 */
const isAfter = (date1, date2) => {
  return date1.getTime() >= date2.getTime()
}
/**
 * 显示计划进度
 */
const showPlan = ({ row, column }) => {
  const currentDay = new Date(column.property)
  const begin = new Date(row[props.ganttConfig.planStart])
  const end = new Date(row[props.ganttConfig.planEnd])
  return currentDay.getTime() >= begin.getTime() && currentDay.getTime() <= end.getTime()
}
/**
 * 显示实际进度
 */
const showReal = ({ row, column }) => {
  const currentDay = new Date(column.property)
  const begin =
    props.ganttConfig.realStart || row[props.ganttConfig.realStart]
      ? new Date(row[props.ganttConfig.realStart])
      : undefined
  const end =
    props.ganttConfig.realEnd || row[props.ganttConfig.realEnd]
      ? new Date(row[props.ganttConfig.realEnd])
      : undefined
  return (
    begin && end && currentDay.getTime() >= begin.getTime() && currentDay.getTime() <= end.getTime()
  )
}
init()
</script>

<style scoped>
.plan {
  display: flex;
  width: calc(100% + 24px);
  height: 16px;
  background-color: limegreen;
  margin: 0 -12px;
}

.real {
  display: flex;
  width: calc(100% + 24px);
  height: 16px;
  background-color: yellow;
  margin: 0 -12px;
}

.empty {
  display: flex;
  width: calc(100% + 24px);
  height: 16px;
  margin: 0 -12px;
}

.legend {
  display: flex;
  line-height: 40px;
  flex-direction: row;
  justify-content: right;
  align-items: center;
  padding: 0 20px;

  * {
    margin: 0 5px;
  }

  i {
    width: 32px;
    height: 16px;
  }
}
</style>
